package com.ybkj.daijia.config;

import com.aliyuncs.CommonRequest;
import com.aliyuncs.CommonResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.ybkj.daijia.Setting;
import com.ybkj.daijia.serverUtils.SettingUtils;
import com.ybkj.daijia.common.Pager;
import com.ybkj.daijia.common.Result;
import com.ybkj.daijia.page.Page;
import com.ybkj.daijia.page.Pageable;
import com.ybkj.daijia.page.impl.PageImpl;
import com.ybkj.daijia.page.impl.PageRequest;
import com.ybkj.daijia.server.model.SmsRecord;
import com.ybkj.daijia.server.model.SmsTemplet;
import com.ybkj.daijia.server.model.SmsTemplet.SmsType;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.commons.lang3.StringUtils;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.HttpServerErrorException;
import org.springframework.web.client.RestTemplate;

/**
 * @author asus
 */
@Component
public class SmsApi {

    /**
     * 创建短信模板
     */
    public static final String SAVE_SMSTEMPLATE = "v1/template/create";
    /**
     * 查询单个短信模板
     */
    public static final String FIND_BYALIAS = "v1/findByAlias";
    /**
     * 批量任务创建
     */
    public static final String BATCH_SMS = "v1/batchTasks/create";
    /**
     * 查询发送短信记录
     */
    public static final String QUERY_SMS_BYPARAM = "v1/smsRecord/queryByParam";
    /**
     * 查询短信剩余条数
     */
    public static final String COUNT_SMS_BALANCE = "v1/apps";
    /**
     * 查询充值记录
     */
    public static final String QUERY_SMS_RECHARGERECORD = "v1/recharge/records";

    private static final Logger logger = LoggerFactory.getLogger(SmsApi.class);
    /**
     * 阿里云短信服务accessKeyId
     */
    private static final String accessKeyId = "LTAI4Fbb2sQaThPoKT32a1Tz";
    /**
     * 阿里云短信服务accessKeySecret
     */
    private static final String accessKeySecret = "rowJrP1qBl8Ea8buH2qB5C46UeOmuA";
    /**
     * 阿里云短信签名
     */
    private static final String signName = "e族出行";
    private static final String product = "Dysmsapi";
    private static final String domain = "dysmsapi.aliyuncs.com";
    @Value("${module.sms.url}")
    private String smsBaseURL;
    @Autowired
    private SettingUtils settingUtils;
    @Autowired
    private RestTemplate restTemplate;

    public String getSmsBaseURL() {
        return smsBaseURL.endsWith("/") ? smsBaseURL : smsBaseURL + "/";
    }

    public void setSmsBaseURL(String smsBaseURL) {
        this.smsBaseURL = smsBaseURL;
    }

    public RestTemplate getRestTemplate() {
        return restTemplate;
    }

    public void setRestTemplate(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    /**
     * 发送短信
     *
     * @param phone     电话
     * @param alias     短信模板别名
     * @param variable  json字符串
     * @param companyId 1L
     * @param type      0,1,2
     * @param sign      短信签名:小咖电脑
     * @return
     */
    public int sendSms(String phone, String alias, String variable, Long companyId, Integer type,
        String sign) {
        System.setProperty("sun.net.client.defaultConnectTimeout", "10000");
        System.setProperty("sun.net.client.defaultReadTimeout", "10000");

        //初始化acsClient,暂不支持region化给i他
        IClientProfile profile = DefaultProfile
            .getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
        try {
            DefaultProfile.addEndpoint("cn-hangzhou", "cn-hangzhou", product, domain);
        } catch (Exception e) {
            e.printStackTrace();
        }
        IAcsClient acsClient = new DefaultAcsClient(profile);

        //组装请求对象-具体描述见控制台-文档部分内容
        SendSmsRequest request = new SendSmsRequest();
        //必填:待发送手机号
        request.setPhoneNumbers(phone);
        //必填:短信签名-可在短信控制台中找到
        request.setSignName(sign);
        //必填:短信模板-可在短信控制台中找到
        request.setTemplateCode(alias);
        //可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
        request.setTemplateParam(variable);
        //hint 此处可能会抛出异常，注意catch
        try {
            SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);

            if (("OK").equals(sendSmsResponse.getCode())) {
                return 0;
            }
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return -1;
    }

    /**
     * 批量发送短信
     *
     * @param phones 多个电话,隔开
     * @return
     */
    public Long batchSendSms(String phones, String message) {
        Setting setting = settingUtils.get();
        try {
            StringBuilder builder = new StringBuilder();
            MultiValueMap<String, String> kv = new LinkedMultiValueMap<String, String>();
            builder.append(getSmsBaseURL());
            builder.append(BATCH_SMS);
            kv.add("phones", phones);
            kv.add("message", message);
            String resultStr = postMultiValueMap(builder.toString(), kv, setting);
            JSONObject jsonObject = new JSONObject(resultStr);
            if (jsonObject.getInt("code") == 0) {
                Long taskId = jsonObject.getLong("id");
                return taskId;
            } else {
                System.err.println("批量发送错误:" + jsonObject.getString("msg"));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 保存短信模板
     */
    public Result<SmsTemplet> create(String name, String type, SmsTemplet smsTemplet) {
        Setting setting = settingUtils.get();
        Result<SmsTemplet> result = new Result<SmsTemplet>();
        try {
            StringBuilder builder = new StringBuilder();
            Map<String, String> kv = new HashMap<String, String>();
            builder.append(getSmsBaseURL());
            builder.append(SAVE_SMSTEMPLATE);
            builder.append(
                "?name={name}&alias={alias}&type={type}&template={template}&appKey={appKey}&companyId={companyId}");
            kv.put("name", name);
            kv.put("alias", smsTemplet.getSmsType().toString());
            kv.put("type", type);
            kv.put("template", smsTemplet.getContent());
            kv.put("companyId", String.valueOf(smsTemplet.getCompanyId()));
            String resultStr = post(builder.toString(), kv, setting);
            if (null != resultStr) {
                JSONObject jo = new JSONObject(resultStr);
                Integer code = jo.getInt("code");
                if (code == 0) {
                    Long id = jo.getLong("id");
                    smsTemplet.setId(id);
                    result.setResult(smsTemplet);
                    result.setSuccess(true);
                    return result;
                } else {
                    System.out.println("resultStr:" + resultStr);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        result.setSuccess(false);
        result.setResult(null);
        return result;
    }

    /**
     * 修改短信模板
     */
//	public Result<SmsTemplet> update(SmsTemplet smsTemplet) {
//		Setting setting = settingUtils.get();
//		Result<SmsTemplet> result = new Result<SmsTemplet>();
//		result.setSuccess(false);
//		try {
//			StringBuilder builder = new StringBuilder();
//			Map<String, String> kv = new HashMap<String, String>();
//			builder.append(getSmsBaseURL());
//			String api=UPDATE_SMSTEMPLATE;
//			api=api.replaceAll("\\{id\\}",String.valueOf(smsTemplet.getId()));
//			builder.append(api);
//			builder.append("?type={type}&template={template}&appKey={appKey}");
//			kv.put("type",smsTemplet.getSmsType().toString());
//			kv.put("template",smsTemplet.getContent());
//			String resultStr = put(builder.toString(), kv, setting);
//			if (resultStr==null) {
//				result.setSuccess(true);
//			}
//		} catch (Exception e) {
//			e.printStackTrace();
//		}
//		return result;
//	}
    public String update(SmsTemplet smsTemplet) {
        Result<SmsTemplet> result = new Result<SmsTemplet>();
        DefaultProfile profile = DefaultProfile
            .getProfile("cn-hangzhou", accessKeyId, accessKeySecret);
        IAcsClient client = new DefaultAcsClient(profile);

        CommonRequest request = new CommonRequest();
        request.setMethod(MethodType.POST);
        request.setDomain(domain);
        request.setVersion("2017-05-25");
        request.setAction("ModifySmsTemplate");
        request.putQueryParameter("RegionId", "cn-hangzhou");
        request.putQueryParameter("TemplateType", smsTemplet.getTemplateType().toString());
        request.putQueryParameter("TemplateName", smsTemplet.getTemplateName());
        request.putQueryParameter("TemplateCode", smsTemplet.getTemplateId());
        request.putQueryParameter("TemplateContent", smsTemplet.getContent());
        request.putQueryParameter("Remark", smsTemplet.getRemark());

        try {
            CommonResponse response = client.getCommonResponse(request);
            System.out.println(response.getData());
            return response.getData();
        } catch (ServerException e) {
            e.printStackTrace();
        } catch (ClientException e) {
            e.printStackTrace();
        }
        return "FAIL";
    }

    public Page<SmsRecord> queryByParam(String phone, String appName, Long startTime, Long endTime,
        Long page, Long limit, Pageable pageable) {
        Setting setting = settingUtils.get();
        StringBuilder builder = new StringBuilder();
        Map<String, String> kv = new HashMap<String, String>();
        builder.append(getSmsBaseURL());
        builder.append(QUERY_SMS_BYPARAM);
        builder.append("?appKey={appKey}");
        if (StringUtils.isNotBlank(phone)) {
            kv.put("phone", phone);
            builder.append("?phone={phone}");
        }
        if (StringUtils.isNotBlank(appName)) {
            kv.put("appName", appName);
            builder.append("&appName={appName}");
        }
        if (startTime != null) {
            kv.put("startTime", String.valueOf(startTime));
            builder.append("&startTime={startTime}");
        }
        if (endTime != null) {
            kv.put("endTime", String.valueOf(endTime));
            builder.append("&endTime={endTime}");
        }
        if (page != null && limit != null) {
            kv.put("page", String.valueOf(page + 1));
            kv.put("limit", String.valueOf(limit));
            builder.append("&page={page}&limit={limit}");
        }
        try {
            String resultStr = get(builder.toString(), kv, setting);
            JSONObject jo = new JSONObject(resultStr);
            Integer code = jo.getInt("code");
            List<SmsRecord> list = new ArrayList<SmsRecord>();
            long total = 0L;
            if (code == 0) {
                total = jo.getLong("total");
                JSONArray jsonArray = jo.getJSONArray("content");
                Gson gson = new GsonBuilder().setDateFormat(com.ybkj.daijia.constant.DateConstant.DATE_TIME_FORMATE).create();
                list = gson.fromJson(jsonArray.toString(), new TypeToken<List<SmsRecord>>() {
                }.getType());
                return new PageImpl<SmsRecord>(list, pageable, total);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public Page<Map<String, Object>> queryRechargeRecord(Integer page, Integer limit) {
        Pageable pageable = new PageRequest(Pager.getPage(), Pager.getLimit());
        Setting setting = settingUtils.get();
        StringBuilder builder = new StringBuilder();
        Map<String, String> kv = new HashMap<String, String>();
        builder.append(getSmsBaseURL());
        builder.append(QUERY_SMS_RECHARGERECORD);
        builder.append("?appkey={appkey}&page={page}&limit={limit}");
        kv.put("appkey", setting.getSecKey());
        kv.put("page", String.valueOf(page + 1));
        kv.put("limit", String.valueOf(limit));
        long total = 0L;
        List<Map<String, Object>> content = new ArrayList<Map<String, Object>>();
        try {
            String resultStr = restTemplate.getForObject(builder.toString(), String.class, kv);
            JSONObject jo = new JSONObject(resultStr);
            Integer code = jo.getInt("code");
            if (code == 0) {
                total = jo.getLong("total");
                JSONArray data = jo.getJSONArray("content");
                for (int i = 0; i < data.length(); i++) {
                    Map<String, Object> map = new HashMap<String, Object>();
                    JSONObject d = data.getJSONObject(i);
                    String details = d.getString("message");
                    map.put("details", details);
                    Double money = d.getDouble("money");
                    map.put("money", money);
                    String created = d.getString("created");
                    map.put("created", created);
                    content.add(map);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new PageImpl<Map<String, Object>>(content, pageable, total);
    }

    public Long querySmsAppBalance() {
        Long balance = 0L;
        Setting setting = settingUtils.get();
        StringBuilder builder = new StringBuilder();
        Map<String, String> kv = new HashMap<String, String>();
        builder.append(getSmsBaseURL());
        builder.append(COUNT_SMS_BALANCE);
        builder.append("?appkey={appkey}&page={page}&limit={limit}");
        kv.put("appkey", setting.getSecKey());
        kv.put("page", String.valueOf(1));
        kv.put("limit", String.valueOf(20));
        try {
            String resultStr = restTemplate.getForObject(builder.toString(), String.class, kv);
            JSONObject jo = new JSONObject(resultStr);
            Integer code = jo.getInt("code");
            if (code == 0) {
                JSONArray data = jo.getJSONArray("content");
                JSONObject d = data.getJSONObject(0);
                balance = d.getLong("balance");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return balance;
    }

    /**
     * 根据别名查询短信模板
     */
    public SmsTemplet findByAlias(Long companyId, SmsType smsType) {
        Setting setting = settingUtils.get();
        try {
            StringBuilder builder = new StringBuilder();
            Map<String, String> kv = new HashMap<String, String>();
            builder.append(getSmsBaseURL());
            builder.append(FIND_BYALIAS);
            builder.append("?alias={alias}&companyId={companyId}&appKey={appKey}");
            kv.put("alias", smsType.toString());
            kv.put("companyId", String.valueOf(companyId));

            String resultStr = get(builder.toString(), kv, setting);
            JSONObject jo = new JSONObject(resultStr);
            Integer code = jo.getInt("code");
            if (code == 0) {
                SmsTemplet templet = new SmsTemplet();
                JSONObject data = jo.getJSONObject("data");
                templet.setId(data.getLong("id"));
                templet.setContent(data.getString("template"));
                templet.setCompanyId(companyId);
                templet.setSmsType(smsType);
                return templet;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public String get(String apiurl, Map<String, String> kv, Setting setting) {
        kv.put("appKey", setting.getSecKey());
        String result = null;
        try {
            result = restTemplate.getForObject(apiurl, String.class, kv);
        } catch (HttpServerErrorException e) {
            e.printStackTrace();
            result = e.getResponseBodyAsString();
        } catch (HttpClientErrorException e) {
            e.printStackTrace();
            result = e.getResponseBodyAsString();
        }
        return result;

    }

    public String postMultiValueMap(String url, MultiValueMap<String, String> kv, Setting setting) {

        kv.add("appKey", setting.getSecKey());

        Set<Entry<String, List<String>>> entries = kv.entrySet();

        Map<String, String> params = new HashMap<String, String>();

        for (Entry<String, List<String>> entry : entries) {
            List<String> values = entry.getValue();
            params.put(entry.getKey(), CollectionUtils.isEmpty(values) ? null : values.get(0));
        }

        RestTemplate rest = new RestTemplate();

        String result = null;

        try {
            result = rest.postForObject(url, kv, String.class);
        } catch (HttpClientErrorException e) {
            logger.error("HttpClientErrorException:code:{},status:{},body:{}", e.getStatusCode(),
                e.getStatusText(), e.getResponseBodyAsString());
            result = e.getResponseBodyAsString();
        } catch (HttpServerErrorException e) {
            logger.error("HttpServerErrorException:{}", e.getResponseBodyAsString());
            result = e.getResponseBodyAsString();
        }

        return result;
    }

    public String post(String apiurl, Map<String, String> kv, Setting setting) {
        kv.put("appKey", setting.getSecKey());
        String result = null;
        try {
            result = restTemplate.postForObject(apiurl, null, String.class, kv);
        } catch (HttpClientErrorException e) {
            logger.error("HttpClientErrorException:code:{},status:{},body:{}", e.getStatusCode(),
                e.getStatusText(), e.getResponseBodyAsString());
            result = e.getResponseBodyAsString();
        } catch (HttpServerErrorException e) {
            logger.error("HttpServerErrorException:{}", e.getResponseBodyAsString());
            result = e.getResponseBodyAsString();
        }
        return result;
    }

    public String put(String apiurl, Map<String, String> kv, Setting setting) {
        kv.put("appKey", setting.getSecKey());
        String result = null;
        try {
            restTemplate.put(apiurl, null, kv);
        } catch (HttpClientErrorException e) {
            e.printStackTrace();
            result = e.getResponseBodyAsString();
        } catch (HttpServerErrorException e) {
            e.printStackTrace();
            result = e.getResponseBodyAsString();
        }
        return result;
    }

    public String delete(String apiurl, Map<String, String> kv, Setting setting) {
        kv.put("appKey", setting.getSecKey());
        String result = null;
        try {
            restTemplate.delete(apiurl, kv);
        } catch (HttpClientErrorException e) {
            result = e.getResponseBodyAsString();
        } catch (HttpServerErrorException e) {
            logger.error("HttpServerErrorException:{}", e.getResponseBodyAsString());
            result = e.getResponseBodyAsString();
        }
        return result;
    }

}
